package com.yida.system.handler;

import java.math.BigDecimal;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import javax.annotation.Resource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.xxl.job.core.handler.annotation.XxlJob;
import com.yida.common.core.constant.CacheConstants;
import com.yida.common.core.enums.DelFlagEnum;
import com.yida.common.core.enums.EnableTypeEnum;
import com.yida.common.core.enums.LimitTimeTypeEnum;
import com.yida.common.redis.service.RedisService;
import com.yida.system.api.domain.SysBlackList;
import com.yida.system.mapper.SysBlackListMapper;

import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.ObjectUtil;
// import lombok.extern.slf4j.Slf4j;
import lombok.extern.slf4j.Slf4j;

/**
 * @Description 系统黑名单数据同步
 * @Author wws
 * @Date 2023-03-22
 */
@Slf4j
@Component
public class SysBlackListSyncHandler {
    @Autowired
    private SysBlackListMapper sysBlackListMapper;

    @Resource
    private RedisService redisService;

    @XxlJob("sysBlackListSyncHandler")
    public void syncDataHandler() {
        String blackWhiteKey = CacheConstants.SYS_CONFIG_KEY + CacheConstants.SYS_CONFIG_BLACK_WHITE_KEY;
        // 判断黑白名单是否开启
        if (redisService.hasKey(blackWhiteKey)) {
            if (EnableTypeEnum.LOCK.getType().equals((String)redisService.getCacheObject(blackWhiteKey))) {
                return;
            }
        }
        // 查询数据库黑名单数据过滤过期数据
        SysBlackList blackList = new SysBlackList();
        blackList.setDelFlag(DelFlagEnum.NORMAL.getType());
        List<String> ipAddressList = sysBlackListMapper.selectSysBlackListList(blackList).stream().filter(item -> {
            // 过滤黑名单限时过期数据
            if (LimitTimeTypeEnum.LIMIT.getType().equals(item.getLimitTimeType()) && LocalDateTimeUtil
                .offset(LocalDateTimeUtil.of(item.getCreateTime()), item.getLimitTime().longValue(), ChronoUnit.MINUTES)
                .isAfter(LocalDateTimeUtil.now())) {
                return Boolean.TRUE;
                // 保留黑名单永久数据
            } else if (LimitTimeTypeEnum.PERMANENT.getType().equals(item.getLimitTimeType())) {
                return Boolean.TRUE;
            }
            return Boolean.FALSE;
        }).map(SysBlackList::getIpAddress).collect(Collectors.toList());
        // 查询缓存黑名单key,并过滤数据库中数据
        List<String> blackListKeys = redisService.scanKeys(CacheConstants.BLACK_LIST + CacheConstants.REDIS_SUFFIX);
        // 过滤缓存中已存在数据库数据
        blackListKeys = blackListKeys.stream().filter(
            item -> !ipAddressList.contains(item.replace(CacheConstants.BLACK_LIST + CacheConstants.REDIS_SUFFIX, "")))
            .collect(Collectors.toList());
        // 缓存黑名单数据为空返回
        if (ObjectUtil.isEmpty(blackListKeys)) {
            return;
        }
        // 处理缓存数据
        List<SysBlackList> resultList = new ArrayList<>(blackListKeys.size());
        blackListKeys.forEach(item -> {
            SysBlackList sysBlackList = new SysBlackList();
            long expire = redisService.getExpire(item);
            if (-1L != expire) {
                sysBlackList.setLimitTime(new BigDecimal(expire));
                sysBlackList.setIpAddress(item.replace(CacheConstants.BLACK_LIST + CacheConstants.REDIS_SUFFIX, ""));
                sysBlackList.setLimitTimeType(LimitTimeTypeEnum.LIMIT.getType());
                sysBlackList.setCreateBy("admin");
                sysBlackList.setCreateTime(new Date());
                resultList.add(sysBlackList);
            }
        });
        for (SysBlackList sysBlackList : resultList) {
            // 插入数据库
            if (1 != sysBlackListMapper.insertSysBlackList(sysBlackList)) {
                log.error("同步缓存IP黑名单数据失败" + LocalDateTimeUtil.now());
            }
        }

    }
}
